package util

import (
	"fmt"
	"reflect"
	"strconv"
)

func Map2Struct(m map[string]interface{}, tagName string, obj interface{}) {

	t := reflect.TypeOf(obj)
	v := reflect.ValueOf(obj)

	if t.Kind() != reflect.Ptr {
		return
	}

	t = t.Elem()
	if t.Kind() != reflect.Struct {
		return
	}

	v = v.Elem()

	var (
		data = make(map[string]interface{})
	)

	for i := 0; i < t.NumField(); i++ {
		var (
			fd = t.Field(i)
			vd = v.Field(i)
		)

		keyName := fd.Tag.Get(tagName)
		if keyName == "" || keyName == "-" {
			continue
		}
		if _, ok := m[keyName]; !ok {
			continue
		}
		if vd.CanSet() {
			vd.Set(reflect.ValueOf(m[keyName]))
		}

		data[keyName] = v.Field(i).Interface()
	}
	return
}

// Struct转成map
func Struct2Map(obj interface{}, tagName string) map[string]interface{} {
	t := reflect.TypeOf(obj)
	v := reflect.ValueOf(obj)

	if t.Kind() == reflect.Ptr {
		t = t.Elem()
		v = v.Elem()
	}

	var data = make(map[string]interface{})
	for i := 0; i < t.NumField(); i++ {
		keyName := t.Field(i).Tag.Get(tagName)
		if keyName != "" && keyName != "-" {
			data[keyName] = v.Field(i).Interface()
		}
	}
	return data
}

// 读取结构体的 tag,返回切片
func Struct2Slice(obj interface{}, tagName, prefix string, ignores ...string) []string {
	t := reflect.TypeOf(obj)

	var data []string
	for i := 0; i < t.NumField(); i++ {
		keyName := t.Field(i).Tag.Get(tagName)
		if keyName != "" && keyName != "-" {
			for _, v := range ignores {
				if v == keyName {
					continue
				}
			}
			if prefix != "" {
				data = append(data, fmt.Sprintf("%v.%v as %v", prefix, keyName, keyName))
			} else {
				data = append(data, fmt.Sprintf("%v", keyName))
			}
		}
	}
	return data
}

func Decimal(num float64, args ...interface{}) float64 {

	var bit = 5
	if len(args) == 1 {
		bit = args[0].(int)
	}

	num, _ = strconv.ParseFloat(fmt.Sprintf(fmt.Sprintf("%%.%vf", bit), num), 64)
	return num
}

func GetStructTagList(obj interface{}, tagName string) []string {
	t := reflect.TypeOf(obj)

	var data []string
	for i := 0; i < t.NumField(); i++ {
		keyName := t.Field(i).Tag.Get(tagName)
		if keyName != "" && keyName != "-" {
			data = append(data, keyName)
		}
	}
	return data
}
